home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 February / macformat-034.iso / mac / Shareware City / Developers / simple-sockets-11-c / Simple Sockets 1.1 ƒ / ip ƒ / ip.c next >
Encoding:
C/C++ Source or Header  |  1995-11-28  |  22.4 KB  |  1,013 lines  |  [TEXT/CWIE]

  1. /*
  2.  * ip.c
  3.  *
  4.  * High routines for dealing with MacTCP. This file has the freedom to
  5.  * be application specific, unlike iplow.c. 
  6.  *
  7.  * These calls will vaguely approximate socket calls.
  8.  *
  9.  * This library was strongly patterned older releases of NewsWatcher,
  10.  * with the blessing of John Norstad.
  11.  *
  12.  * Mike Trent 8/94
  13.  */
  14. /*
  15.  * Since it's initial release in April 1995, I received some good feedback
  16.  * on my code.  My thanks go out to the following people (in chronological order):
  17.  *
  18.  *         Lim Wai Kong David <limwaiko@iscs.nus.sg>
  19.  *        Matthias Ulrich Neeracher <neeri@iis.ee.ethz.ch>
  20.  *        David M. Asbell <udasbell@mcs.drexel.edu>
  21.  * 30 May 95
  22.  */
  23.  
  24. /* ANSI Includes */
  25. #include <stdio.h>  /* for num2dot's sprintf */
  26. #include <string.h>
  27.  
  28. /* Additional Mac Includes */
  29. #include <MacTCPCommonTypes.h>
  30. #include <AddressXlation.h>
  31. #include <MiscIPPB.h>
  32. #include <UDPPB.h>
  33. #include <TCPPB.h>
  34. #include <GetMyIPAddr.h>
  35.  
  36.  
  37. /* Local Includes */
  38. #include "butil.h"
  39. #include "ip.h"
  40. #include "iplow.h"
  41. #include "iperr.h"
  42.  
  43.  
  44. /* Global to this module */
  45.  
  46. mac_socket streams[kNumSockets];
  47. int    initedp = 0;
  48.  
  49. /* Private Functions */
  50.  
  51. int FindFreeSocket(void);
  52. void ReleaseAll(void);
  53.  
  54.  
  55. /**
  56.  **
  57.  ** MISC ROUTINES
  58.  **
  59.  **/
  60.  
  61.  
  62. /* InitMacTCP
  63.  * - Initializes the MacTCP driver via iplow.c , zero's out the module-global
  64.  *     streams array, and specifices an atexit routine to free memory. 
  65.  * Returns OSErr: result of LowInitMacTCP
  66.  */
  67.  
  68. OSErr InitMacTCP(void)
  69. {
  70.     OSErr err;
  71.     
  72.     if (initedp == 1) return noErr;    /*handle multiple calls gracefully */
  73.     initedp = 1;
  74.     
  75.     bzero((char *)streams, (sizeof(mac_socket) * kNumSockets));
  76.     
  77.     /*
  78.     if (atexit(ReleaseAll)) {
  79.         return -1;
  80.     }
  81.     * - Removed December 11, 1994
  82.     */
  83.     
  84.     err = LowInitMacTCP();
  85.     SetSpin(nil);
  86.     return err;
  87. }
  88.  
  89.  
  90. /* DisposeMacTCP
  91.  * - calls ReleaseAll, so that connections can be closed and memory
  92.  *   can be disposed of.
  93.  *   
  94.  *   Originally this was handled with "atexit(ReleaseAll)" but this
  95.  *   seems like a better way to do it.
  96.  */
  97. void DisposeMacTCP(void)
  98. {
  99.     ReleaseAll();
  100.     
  101.     initedp = 0;    /* Ok, I've provided this, but I'm not going to support it - yet */
  102. }
  103.  
  104.  
  105. /* FindFreeSocket
  106.  * - Searches through streams array looking for a free 'socket'
  107.  * Returns int: socket id 0-31, -1 if array is full.
  108.  */
  109.  
  110. int FindFreeSocket(void)
  111. {
  112.     int x;
  113.     
  114.     for (x = 0; x < (kNumSockets -1); x++) {
  115.         if (streams[x].stream == 0) {
  116.             return x;
  117.         }
  118.     }
  119.     return -1;
  120. }
  121.  
  122. /* ReleaseAll
  123.  * - Runs when program quits normally, and frees memory from MacTCP
  124.  */
  125. void ReleaseAll(void)
  126. {
  127.     OSErr err;
  128.     int x;
  129.     
  130.     for (x=0; x<(kNumSockets -1); x++)
  131.         if (streams[x].stream > 0)
  132.             switch (streams[x].type) {
  133.             case IPPROTO_TCP:
  134.                 err = LowTCPRelease(streams[x].stream);
  135.                 break;
  136.             case IPPROTO_UDP:
  137.                 err = LowUDPRelease(streams[x].stream);
  138.                 break;
  139.             }
  140.     //error is ignored
  141.     return;
  142. }
  143.  
  144. /* SetSpin
  145.  * - Sets the event routine so that the Macintosh can continue
  146.  *   processing events while waiting for a MacTCP routine to return.
  147.  *     spinRoutine is a procedure pointer type. A routine passed
  148.  *     to it will be called during network access times. A nil value
  149.  *     resets the spin routine to the iplow default routine.
  150.  */
  151.  
  152.  
  153. void SetSpin(Spin spinRoutine)
  154. {
  155.     LowSetSpin(spinRoutine);
  156. }
  157.  
  158.  
  159. /**
  160.  **
  161.  ** DNS COMMANDS
  162.  **
  163.  **/
  164.  
  165.  
  166. /* num2dot
  167.  * - Quickly converts an IP number in u_long form to dot notation. The dot notation
  168.  * is stored in *dot. Unless the programmer has special knowledge of the u_longs being
  169.  * passed to num2dot, *dot should be at least 16 characters long (xxx.xxx.xxx.xxx\0).
  170.  */
  171.  
  172. void num2dot(unsigned long ip, char *dot)
  173. {
  174.     unsigned char *tmp;
  175.     
  176.     tmp = (unsigned char *)&ip;
  177.     (void) sprintf(dot, (const char *)"%d.%d.%d.%d", tmp[0], tmp[1], tmp[2], tmp[3]);
  178. }
  179.  
  180.  
  181. /* ConvertStrToAddr
  182.  * - Executes a DNS look up. *name is a string containing either an IP Number in
  183.  *   dot notation, or a DNS name
  184.  * Returns: MacTCP OSErr.
  185.  */
  186.  
  187. OSErr ConvertStrToAddr(char *name, unsigned long *ipNum)
  188. {
  189.     OSErr err;
  190.     
  191.     err = LowStringToAddr(name, ipNum);
  192.     return err;
  193. }
  194.  
  195.  
  196. /* GetHostByName
  197.  * - Emulates the UNIX routine by the same name.  When passed a DNS name, 
  198.  *   GetHostByName will return the long int IP Number.
  199.  * Returns: unsigned long IP Number; 0 = error
  200.  */
  201.  
  202. unsigned long GetHostByName(char *name)
  203. {
  204.     OSErr err;
  205.     unsigned long num;
  206.     
  207.     if ((err = LowStringToAddr(name, &num)) != noErr) {
  208.         gMacErrno = err;
  209.         return 0;
  210.     }
  211.     return num;
  212. }
  213.  
  214.  
  215. /* GetProtoByName
  216.  * - returns the number associated with a named protocol. Only "tcp" and
  217.  *   "udp" are supported via MacTCP. While this bears some resemblance to
  218.  *     the UNIX function of the same name, it really is different, returning
  219.  *     a simple int (for use in sockaddr_in.sin_port) rather than a complex
  220.  *   record. This is mostly because MacTCP supports only UDP and TCP.
  221.  * Returns int: protocol number, 0 = error.
  222.  */
  223.  
  224. int GetProtoByName(char *name)
  225. {
  226.     if (!strcmp(name, "tcp")) {
  227.         return IPPROTO_TCP;
  228.     } else if (!strcmp(name, "udp")) {
  229.         return IPPROTO_UDP;
  230.     } else {
  231.         return 0;
  232.     }
  233. }
  234.  
  235.  
  236. /* GetHostName
  237.  * Returns the DNS name of the current machine. If there is no DNS name, the
  238.  * routine will return 0, and the machine's IP number in dot-notation will
  239.  * be stored in *name.
  240.  * Returns int: 0 noErr, -1 err.
  241.  */
  242.  
  243. int GetHostName(char *name, int namelen)
  244. {
  245. //#pragma unused (namelen)
  246.     OSErr err;
  247.     unsigned long ip;
  248.     
  249.     if ((err = LowGetMyIP(&ip)) != noErr) {
  250.         gMacErrno = err;
  251.         return -1;
  252.     }
  253.     if ((err = LowAddrToName(ip, name)) != noErr) {
  254.         num2dot(ip, name);
  255.         //return -1;
  256.     }
  257.     return 0;
  258. }
  259.  
  260. /* GetHostNameOnly
  261.  * Returns the DNS name of the current machine. If there is no DNS name, the
  262.  * routine will return -1.
  263.  * Returns int: 0 noErr, -1 err.
  264.  */
  265.  
  266. int GetHostNameOnly(char *name)
  267. {
  268.     OSErr err;
  269.     unsigned long ip;
  270.     
  271.     if ((err = LowGetMyIP(&ip)) != noErr) {
  272.         gMacErrno = err;
  273.         return -1;
  274.     }
  275.     if ((err = LowAddrToName(ip, name)) != noErr) {
  276.         gMacErrno = err;
  277.         return -1;
  278.     }
  279.     return 0;
  280. }
  281.  
  282.  
  283. /* GetMyIPDot
  284.  * - Returns the dot notation IP Address of the current machine in *name.
  285.  * Returns int: 0 noError, -1 err
  286.  */
  287.  
  288. int GetMyIPDot(char *num)
  289. {
  290.     OSErr err;
  291.     unsigned long ip;
  292.     
  293.     if ((err = LowGetMyIP(&ip)) != noErr) {
  294.         gMacErrno = err;
  295.         return -1;
  296.     }
  297.     num2dot(ip, num);
  298.     return 0;
  299. }
  300.  
  301.  
  302. /* GetMyIPNum
  303.  * - As above, but it returns an unsigned long IP number, rather than a
  304.  *   dot notation ip number.
  305.  * Returns unsigned long IP Number; -1 = error
  306.  */
  307.  
  308. unsigned long GetMyIPNum(void)
  309. {
  310.     OSErr err;
  311.     unsigned long ip;
  312.     
  313.     if ((err = LowGetMyIP(&ip)) != noErr){
  314.         gMacErrno = err;
  315.         return -1;
  316.     }
  317.     return ip;
  318. }
  319.  
  320.  
  321. /* getsockname
  322.  * - returns the local address associated with a socket. 
  323.  * Returns int: 0 noErr, -1 err
  324.  */
  325.  // Added on Wed 1/4/95. Not tested
  326.  /* Contributed by Lim Wai Kong David <limwaiko@iscs.nus.sg> */
  327.  
  328. int getsockname (int sock, struct sockaddr_in *localaddr, int *addrlen)
  329. {
  330.     OSErr err = noErr;
  331.     
  332.     if ((sock < 0) || (sock >= kNumSockets)) {
  333.         gErrno = EBADF;                       // bad socket
  334.         return -1;
  335.     }
  336.     
  337.     localaddr->sin_addr = streams[sock].localHost;
  338.     localaddr->sin_port = streams[sock].localPort;
  339.     localaddr->sin_family = AF_INET;
  340.             
  341.     *addrlen = sizeof (struct sockaddr_in);
  342.  
  343.     return 0;
  344. }
  345.  
  346.  
  347. /**
  348.  **
  349.  ** GENERAL IP ROUTINES
  350.  **
  351.  **/
  352.  
  353.  
  354.  
  355. /* socket
  356.  * - Creates MacTCP stream connection.
  357.  *        type - IPPROTO_TDP for tcp, IPPROTO_UDP for udp
  358.  * Returns int: socket if 0-31, -1 if error.
  359.  */
  360. //int socket (int type)
  361. /* socket
  362.  * - Creates a MacTCP "stream" connection
  363.  *        family   - Ignored.
  364.  *        type     - Ignored.
  365.  *        protocol - Specifies either TCP/IP (6)  or UDP/IP (17).
  366.  *    Returns 0-31 if successful, -1 if error.  If gErrno == EIO, additional information
  367.  *                   is stored in gMacErrno
  368.  *
  369.  *    Revised 12/26/94
  370.  */
  371. /* Site for future revision: Dispatch on type, not protocol */
  372. int socket(int family, int type, int protocol)
  373. //#pragma unused (family)
  374. //#pragma unused (type)
  375. {
  376.     OSErr err;
  377.     int sock;
  378.     
  379.     sock = FindFreeSocket();
  380.     if (sock < 0) {
  381.         gErrno = EMFILE;
  382.         return -1;
  383.     }
  384.     
  385.     switch (protocol) {
  386.       case IPPROTO_TCP:
  387.         err = LowTCPCreate(&(streams[sock].stream), streams);
  388.         break;
  389.       case IPPROTO_UDP:
  390.           err = LowUDPCreate(&(streams[sock].stream), 0, streams);
  391.           break;
  392.       default:
  393.           gErrno = ESOCKTNOSUPPORT;
  394.           return -1;
  395.     }
  396.         
  397.     if (err != noErr) {
  398.         gMacErrno = err; /* if mem err, gErrno = ENOBUFS */
  399.         gErrno = EIO;
  400.         return -1;
  401.     }
  402.     streams[sock].type = protocol;
  403.     return sock;
  404. }
  405.  
  406. /* connect
  407.  * - creates an active TCP or UDP stream. 
  408.  * Returns int: 0 noErr, -1 err
  409.  */
  410. int connect(int sock, struct sockaddr_in *raddr, int alen)
  411. //#pragma unused (alen)
  412. {
  413.     OSErr err = noErr;
  414.     
  415.     if ((sock < 0) || (sock >= kNumSockets)) {
  416.         gErrno = EBADF;   /* bad socket */
  417.         return -1; 
  418.     }
  419.     /*if (streams[sock].stream == 0) {
  420.         gErrno = ENOTSOCK;
  421.         return -1;
  422.     } Useless */
  423.     if (streams[sock].connected) {
  424.         gErrno = EISCONN;
  425.         return -1;
  426.     }
  427.     streams[sock].remoteHost = raddr->sin_addr;
  428.     streams[sock].remotePort = raddr->sin_port;
  429.         
  430.     switch (streams[sock].type) {
  431.       case IPPROTO_TCP:
  432.           err = LowTCPActiveOpen (streams[sock].stream, (char)30, streams[sock].remoteHost,
  433.                             streams[sock].remotePort, &(streams[sock].localHost),
  434.                             &(streams[sock].localPort));
  435.         break;
  436.       case IPPROTO_UDP:
  437.           /* Do nothing. UDP merely records the destination for later use. Comer III p.70 
  438.              The important info was recorded in the two lines preceeding the switch */
  439.           break;
  440.     }
  441.           
  442.     if (err != noErr) {
  443.         gMacErrno = err;
  444.         gErrno = EIO;
  445.         return -1;
  446.     }
  447.     
  448.     streams[sock].connected = 1;
  449.     return 0;
  450. }
  451.  
  452.  
  453.  
  454. /* write
  455.  * - sends data over the stream.
  456.  *      sock - socket descriptor
  457.  *      data - Ptr to data (also char *)
  458.  *      len  - length of mem pointed to in Ptr.
  459.  * Returns int: len
  460.  */
  461.  
  462. int write (int sock, Ptr data, int len)
  463. {
  464.     OSErr err;
  465.     struct wdsEntry myWDS[2];    /* global write data structure */
  466.  
  467.     if ((sock < 0) || (sock >= kNumSockets)) {
  468.         gErrno = EBADF;   /* bad socket */
  469.         return -1; 
  470.     }
  471.     if (streams[sock].stream == 0) {
  472.         gErrno = ENOTSOCK;
  473.         return -1;
  474.     }
  475.     if (!streams[sock].connected) {
  476.         gErrno = EPIPE; 
  477.         return -1;
  478.     }
  479.     if (len == 0) return 0;
  480.     
  481.     if (len > 32767) {
  482.         gErrno = EFBIG;
  483.         return -1;
  484.     }
  485.  
  486.     myWDS[1].length = 0;
  487.     myWDS[1].ptr = nil;
  488.     
  489.     switch(streams[sock].type) {
  490.       case IPPROTO_TCP:    
  491.         myWDS[0].length = len;
  492.         myWDS[0].ptr = data;
  493.     
  494.         err = LowTCPSend(streams[sock].stream, (char)30, (Ptr)myWDS);
  495.         
  496.         if (err != noErr) {
  497.             gMacErrno = err;
  498.             gErrno = EIO;
  499.             return -1;
  500.         }
  501.         break;
  502.       case IPPROTO_UDP:
  503.          {
  504.              unsigned short mtu;
  505.              int lenidx=0;
  506.              
  507.              if (streams[sock].mtu == 0) {
  508.                  err = LowUDPMTU(streams[sock].stream, streams[sock].remoteHost, &streams[sock].mtu);
  509.                  if (err != noErr) {
  510.                      streams[sock].mtu = 0;
  511.                      gErrno = EIO;
  512.                      gMacErrno = err;
  513.                      return -1;
  514.                  }
  515.              }
  516.              mtu = streams[sock].mtu - kHeaderSize;
  517.              
  518.              /* Site for future revision: Don't split up the UDP call! */
  519.              while (lenidx < len) {
  520.                  myWDS[0].length = (mtu < (len - lenidx) ? mtu : (len - lenidx));
  521.                  myWDS[0].ptr = &data[lenidx];
  522.                  lenidx += myWDS[0].length;
  523.                  
  524.                  err = LowUDPWrite(streams[sock].stream, (Ptr)myWDS, streams[sock].remoteHost,
  525.                                    streams[sock].remotePort);
  526.                  if (err != noErr) {
  527.                      gErrno = EIO;
  528.                      gMacErrno = err;
  529.                      return -1;
  530.                  }
  531.              }
  532.         }
  533.         break;
  534.     }
  535.     return len;
  536. }
  537.  
  538.  
  539. /* read
  540.  * - reads data from a socket. It will block if there is no data.
  541.  *    sock - socket descriptor
  542.  *      buf  - memory buffer to be written to
  543.  *      len  - length of memory buffer
  544.  * Returns int: number of bytes read, or -1
  545.  */
  546. /* 28 Aug 95 - Modified routine to be cognizant of the presence of unread data
  547.  * on a stream.
  548.  */
  549. int read (int sock, Ptr buf, int len)
  550. {
  551.     OSErr err = noErr; // *MDT 8/28/95
  552.     int tmplen = len;
  553.     unsigned long dmy1=0;
  554.     unsigned short dmy2=0;
  555.     TCPStatusPB statusPB; // *MDT 8/28/95
  556.     
  557.  
  558.     if ((sock < 0) || (sock >= kNumSockets)) {
  559.         gErrno = EBADF;   /* bad socket */
  560.         return -1; 
  561.     }
  562.     if (streams[sock].stream == 0) {
  563.         gErrno = ENOTSOCK;
  564.         return -1;
  565.     }
  566.     if (!streams[sock].connected) {
  567.         gErrno = EPIPE; 
  568.         return -1;
  569.     }
  570.     if (len == 0) return 0;
  571.     if (len > 32767) {
  572.         gErrno = EFBIG;
  573.         return -1;
  574.     }
  575.  
  576.     switch(streams[sock].type){
  577.     case IPPROTO_TCP:
  578.         err = LowTCPRcv (streams[sock].stream, (char)30, buf, &tmplen);
  579.         break;
  580.     case IPPROTO_UDP:
  581.         err = LowUDPRead (streams[sock].stream, (char)30, buf, &tmplen, &dmy1, &dmy2); 
  582.         break;
  583.     }        
  584.  
  585.     if (err != noErr) {
  586.         gMacErrno = err;
  587.         gErrno = EIO;
  588.         return -1;
  589.     }
  590.     
  591.     // *MDT+9 8/28/95 Fixed clearing hasData flag.
  592.     if (streams[sock].type == IPPROTO_TCP) {
  593.         err = LowTCPStatus(streams[sock].stream, &statusPB);
  594.         if (err != noErr) {
  595.             gMacErrno = err;
  596.             gErrno = EIO;
  597.             return -1;
  598.         }
  599.         if (statusPB.amtUnreadData == 0) {
  600.             streams[sock].hasData = 0;        //user read all the data
  601.         }
  602.     }
  603.     return tmplen;
  604. }
  605.  
  606.  
  607. /* close
  608.  * - closes a stream and releases it's memory
  609.  *    sock - socket descriptors
  610.  * Returns int: 0 noErr, -1 err
  611.  */
  612. int close(int sock)
  613. {
  614.     OSErr err;
  615.  
  616.     if ((sock < 0) || (sock >= kNumSockets)) {
  617.         gErrno = EBADF;   /* bad socket */
  618.         return -1; 
  619.     }
  620.     if (!streams[sock].connected) {
  621.         gErrno = EBADF; 
  622.         return -1;
  623.     }
  624.     
  625.     switch (streams[sock].type) {
  626.       case IPPROTO_TCP:
  627.         err = LowTCPClose (streams[sock].stream,(char) 30);
  628.         (void) LowTCPRelease(streams[sock].stream);
  629.         break;
  630.       case IPPROTO_UDP:
  631.           err = LowUDPRelease(streams[sock].stream);
  632.           break;
  633.     }
  634.     
  635.     if ((err != noErr) && (err != connectionDoesntExist)) {
  636.         gMacErrno = err;
  637.         gErrno = EIO;
  638.         
  639.         /* Might as well just call the stream closed */
  640.         bzero((char *)&(streams[sock]), sizeof(mac_socket));
  641.         return -1;
  642.     }
  643.  
  644.     /* zero out entire structure */
  645.     bzero((char *)&(streams[sock]), sizeof(mac_socket));
  646.     
  647.     return 0;
  648. }
  649.  
  650.  
  651.  
  652. /**
  653.  **
  654.  **  TCP SECTION
  655.  **
  656.  **/
  657.  
  658.  
  659. /* select
  660.  * - Reports which streams has unread data queued in them. See UNIX man page.
  661.  *        nfds    - should always be equal to kNumSockets
  662.  *        *readfs - bitmap of sockets; Specifies streams to check on IN, and
  663.  *                  returns the streams w/ pending data on OUT.
  664.  * Returns int : number of sockets w/ pending data.
  665.  */
  666. /* 30 May 95 - Modified routine so that if timeout != nil, data will be polled
  667.  * at least once, even if tv_sec = tv_usec = 0.  This was suggested by
  668.  * David M. Asbell (udasbell@mcs.drexel.edu); he has my thanks.
  669.  */
  670. /* 28 Aug 95 - Allowed tv_usec to have some (minor) effect on waittil. Also, 
  671.  * removed stupid debug variable that was released accidentally.
  672.  */ 
  673. int select (int nfds, unsigned long *readfs, struct timeval *timeout)
  674. {
  675.     int sock, total = 0;
  676.     unsigned long bitmap = 0;
  677.     long waittil;
  678.     
  679.     if (timeout) waittil = TickCount() + (60 * (timeout->tv_sec + (timeout->tv_usec / 1000))); // *MDT 8/28/95
  680.     
  681.     for (;;) {
  682.                 
  683.         for (sock=0; sock<nfds; sock++) {
  684.             if (*readfs & (1 << sock)) {  /* if socket selected */
  685.                 if (streams[sock].stream == 0) {    /* if selected socket isn't allocated */
  686.                     gErrno = EBADF;
  687.                     gMacErrno = 0;
  688.                     return -1;
  689.                 }
  690.                 if (streams[sock].hasData == 1) { // *MDT 8/28/95
  691.                     bitmap |= (1 << sock);  // select bit 
  692.                     total++;
  693.                 }
  694.             } /* if */
  695.         } /* for (sock) */
  696.         
  697.         if (total) break;    /* if we have unread data, break */
  698.  
  699.         if ((timeout) && (waittil < TickCount()) ) /* if we have timed out, break. Note that
  700.                                                       total still = 0 */
  701.             break;
  702.  
  703.         LowSpin();  /* give a hoot - call the spin routine! */
  704.         
  705.     }/* for (;;) */
  706.     *readfs = bitmap;
  707.     return (total);
  708. }
  709.  
  710. /* OBSOLETE */
  711.  
  712. int old_select (int nfds, unsigned long *readfs){
  713.     OSErr err;
  714.     int sock, total = 0;
  715.     int ans = 0;
  716.     
  717.     for (sock=0; sock<nfds; sock++) {
  718.         if (*readfs & (1 << sock)) {  /* if socket selected */
  719.             if (streams[sock].stream == 0) {    /* if selected socket isn't allocated */
  720.                 gErrno = EBADF;
  721.                 gMacErrno = 0;
  722.                 return -1;
  723.             }
  724.             if (streams[sock].type == IPPROTO_UDP) 
  725.                 continue;                         /* skip UDP sockets */
  726.             if ((err = LowTCPSelect(streams[sock].stream, &ans)) != noErr) {
  727.                 gErrno = EIO;
  728.                 gMacErrno = err;
  729.                 return -1;
  730.             }
  731.             if (ans == 0) {
  732.                 *readfs &= ~(1 << sock);  // unselect bit 
  733.             } else {
  734.                 total++;
  735.             }
  736.         }
  737.     }
  738.     return (total);
  739. }
  740.  
  741.  
  742. /* bind
  743.  * - Specifies port for server to listen to.
  744.  *         sock  - Socket to bind
  745.  *        *name - address to bind socket to.  Traditionally, name->sin_family == AF_INET,
  746.  *                though name->sin_family is ignored in this implementation.  name->sin_addr
  747.  *                must equal INADDR_ANY ((u_long)0x00000000) or the local system address,
  748.  *                though, again, in this case, name->sin_addr is ignored.  name->sin_port
  749.  *                specifies the port number the socket is to be bound to. Traditionally,
  750.  *                ports between 1 and 1023 (inclusive) are reserved for the high and mighty;
  751.  *                this implementation does not preserve the notion of reserved ports.
  752.  *        alen  - the length of the *name field.  Ignored.
  753.  * Returns 0 if successful, -1 if error.  The specific error code is stored in gErrno. If
  754.  *                gErrno == EIO, additional information is stored in gMacErrno.
  755.  *
  756.  * Revised 12/26/94
  757.  * Revised 3/14/95 - see below.
  758.  */
  759. /* Site for future revision: Currently, I don't check to see if other processes
  760.    have bound to the desired port. */
  761. int bind (int sock, struct sockaddr_in *name, int alen)
  762. //#pragma unused (alen)
  763. {
  764.     int x;
  765.     
  766.     if ((sock < 0) || (sock >= kNumSockets)) {
  767.         gErrno = EBADF;   /* unix bad socket */
  768.         return -1; 
  769.     }
  770. /* Apparently, one can bind UDP sockets.  The RPC portmapper infact binds a UDP
  771.  * and a TCP socket to port 111 at the same time.  I didn't read Comer carefully.
  772.  * See below ...
  773.  */
  774. /*    if (streams[sock].type == IPPROTO_UDP) {
  775.         gErrno = EBADF;
  776.         gMacErrno = 0;
  777.         return -1;
  778.     }*/
  779.     if ((name->sin_port < 1) || (name->sin_port > 32767)) {
  780.         gErrno = EADDRNOTAVAIL; /* bad port num */
  781.         return -1;
  782.     }
  783.     if (streams[sock].bound) {    
  784.         gErrno = EINVAL;
  785.         return -1;
  786.     }
  787.     for (x=0; x< (kNumSockets -1); x++) {
  788.         if ((name->sin_port == streams[x].localPort) && (streams[x].bound) && 
  789.                             (streams[x].type == streams[sock].type)) {
  790.         /* if someone else is bound to this port ... return error.  */
  791.         /* this if was modified to make sure a UDP socket and a TCP socket CAN connect to
  792.          * the same port, but two or more of like-kinds cannot bind to the port.
  793.          * 14 Mar 95 - MDT
  794.          */
  795.             gErrno= EADDRINUSE;
  796.             return -1;
  797.         }
  798.     }
  799.     streams[sock].bound = 1;
  800.     streams[sock].localPort = name->sin_port;
  801.     return 0;
  802. }
  803.  
  804. /* there is no listen */
  805. int listen(int socket, int queuelen)
  806. //#pragma unused (socket)
  807. //#pragma unused (queuelen)
  808. {
  809.     /* Welcome to Macintosh */
  810.     return 0;
  811. }
  812.  
  813. /* accept
  814.  * - Passively waits for a TCP connection. 
  815.  *        sock - specifies socket to wait on
  816.  *        *sin - returns address of calling service.
  817.  *        alen - Ignored.
  818.  * Returns 0 if successful, -1 if not. If gErrno == EIO, additional information is stored
  819.  *                in gMacErrno.
  820.  *
  821.  * Revised 12/26/94
  822.  */
  823. int accept (int sock, struct sockaddr_in *sin, int *alen)
  824. {
  825. //#pragma unused (alen)
  826.     OSErr err;
  827.     unsigned long remoteHost;
  828.     unsigned short remotePort;
  829.     int tmp;
  830.     
  831.     if ((sock < 0) || (sock >= kNumSockets)) {
  832.         gErrno = EBADF;   /* unix bad socket */
  833.         return -1; 
  834.     }
  835.     if (streams[sock].type == IPPROTO_UDP) {
  836.         gErrno = EBADF;
  837.         return -1;
  838.     }
  839.     if ((streams[sock].stream == 0) || (streams[sock].localPort == 0)) {
  840.         gErrno = ENOTSOCK;
  841.         return -1;
  842.     }
  843.     if (streams[sock].connected) {
  844.         gErrno = EOPNOTSUPP; /* or something - the port is busy already */
  845.         return -1;
  846.     }
  847.     if (!streams[sock].bound) {
  848.         /* socket is not bound to port*/
  849.         return -1;
  850.     }
  851.     if ((tmp = FindFreeSocket()) == -1) {    
  852.         /* out of sockets */
  853.         return -1;
  854.     }
  855.         
  856.     remotePort = remoteHost = 0;
  857.     
  858.     err = LowTCPPassiveOpen(streams[sock].stream, (char)0, &remoteHost, &remotePort,
  859.                             &(streams[sock].localHost),&(streams[sock].localPort));
  860.     if (err != noErr) {
  861.         gMacErrno = err;
  862.         gErrno = EIO;
  863.         return -1;
  864.     }
  865.     
  866.     bcopy((char *)&streams[sock], (char *)&streams[tmp], sizeof(mac_socket)); /* copy current socket into tmp */
  867.     
  868.     /* accept call was successful */
  869.     /* create new stream for original socket */
  870.     err = LowTCPCreate(&(streams[sock].stream), streams);
  871.     if (err != noErr) {
  872.         /* something bad happened */
  873.         gErrno = EIO;
  874.         gMacErrno = err;
  875.         /* restore everything back to normal */
  876.         streams[sock].stream = streams[tmp].stream;
  877.         bzero((char *)&streams[tmp], sizeof(mac_socket));
  878.         return -1;
  879.     }
  880.  
  881.     streams[sock].connected = 0;    /* unset connected flag for sock */
  882.     streams[tmp].connected = 1;
  883.     streams[tmp].bound = 0;            /* unset bound flag for tmp      */
  884.     sin->sin_port = remotePort;
  885.     sin->sin_addr = remoteHost;
  886.     return (tmp);
  887. }
  888.  
  889.  
  890. /**
  891.  **
  892.  ** UDP/IP ROUTINES
  893.  **
  894.  **/
  895.  
  896. int recvfrom (int sock, char *buf, int len, int flags, struct sockaddr_in *sin, int *alen)
  897. {
  898. //#pragma unused (alen)
  899.     OSErr err;
  900.     int tmplen = len;
  901.     unsigned long address=0;
  902.     unsigned short port=0;
  903.  
  904.     if ((sock < 0) || (sock >= kNumSockets)) {
  905.         gErrno = EBADF;   /* bad socket */
  906.         return -1; 
  907.     }
  908.     if (streams[sock].stream == 0) {
  909.         gErrno = ENOTSOCK;
  910.         return -1;
  911.     }
  912.     /*if (!streams[sock].connected) {
  913.         gErrno = EISNCONN;
  914.         return -1;
  915.     } DUH !! Don't be stupid! */
  916.     if (streams[sock].type == IPPROTO_TCP) {
  917.         gErrno = EBADF;   /* bad socket */
  918.         return -1; 
  919.     }
  920.  
  921.     if ((len == 0) || (len > 32767)) 
  922.         return 0; /* this is rough, but for debug */
  923.     
  924.     /* This bit is thanks to Matthias Ulrich Neeracher <neeri@iis.ee.ethz.ch>, author
  925.      * of GUSI, who took the time to read my code (even with all it's crappy commenting)
  926.      * and point out mistakes. Thanks!
  927.      */    
  928.     if (sin) {
  929.         address = sin->sin_addr;
  930.         port  = sin->sin_port;
  931.     }
  932.     
  933.     err = LowUDPRead (streams[sock].stream, (char)0, buf, &tmplen, &address, 
  934.                         &port); 
  935.     if (err != noErr) {
  936.         gMacErrno = err;
  937.         gErrno = EIO;
  938.         return -1;
  939.     }
  940.     streams[sock].hasData = 0; /* assume all data has been read, since we can't get any more info */
  941.     
  942.     if (sin) {
  943.         sin->sin_addr = address;
  944.         sin->sin_port = port;
  945.     }
  946.     
  947.     return tmplen;
  948. }
  949.  
  950.  
  951.  
  952.  
  953. int sendto (int sock, char *data, int len, int flags, struct sockaddr_in *sin, int alen)
  954. {
  955. //#pragma unused (alen)
  956.     OSErr err;
  957.     struct wdsEntry myWDS[2];    /* global write data structure */
  958.     unsigned short mtu;
  959.     int lenidx=0;
  960.  
  961.  
  962.     if ((sock < 0) || (sock >= kNumSockets)) {
  963.         gErrno = EBADF;   /* bad socket */
  964.         return -1; 
  965.     }
  966.     if (streams[sock].stream == 0) {
  967.         gErrno = ENOTSOCK;
  968.         return -1;
  969.     }
  970. /*    if (!streams[sock].connected) {
  971.         gErrno = EISNCONN; 
  972.         return -1;
  973.     }*/
  974.     if (streams[sock].type != IPPROTO_UDP) {
  975.         gErrno = EBADF;   /* UDP ONLY PLEASE! */
  976.         return -1; 
  977.     }
  978.     if ((len == 0) || (len > 32767)) return 0;
  979.  
  980.     myWDS[1].length = 0;
  981.     myWDS[1].ptr = nil;
  982.     
  983.     if (streams[sock].mtu == 0) {
  984.         err = LowUDPMTU(streams[sock].stream, sin->sin_addr, &streams[sock].mtu);
  985.         if (err    != noErr) {
  986.             streams[sock].mtu = 0;
  987.             gErrno = EIO;
  988.             gMacErrno = err;
  989.             return -1;
  990.         }
  991.     }
  992.     mtu = streams[sock].mtu - kHeaderSize;
  993.     
  994.     while (lenidx < len) {
  995.         myWDS[0].length = (mtu < (len - lenidx) ? mtu : (len - lenidx));
  996.         myWDS[0].ptr = &data[lenidx];
  997.         lenidx += myWDS[0].length;
  998.         
  999.         err = LowUDPWrite(streams[sock].stream, (Ptr)myWDS, sin->sin_addr, sin->sin_port);
  1000.         if (err != noErr) {
  1001.             gErrno = EIO;
  1002.             gMacErrno = err;
  1003.             return -1;
  1004.         }
  1005.     }
  1006.     return len;
  1007. }
  1008.  
  1009.  
  1010.  
  1011.  
  1012.  
  1013.